我們已經可以處理web requrest,再來就要依照對應的 "resources" 到對應的地方
中間的過程就先忽略,今天主要來聊route
自古以來,其實就是依照method/uri/header來判斷我要去哪邊找東西,丟什麼東西回去
最單純的是前面apache/nginx在設定裡就找到資源,或是幫我們分好由app自己回覆對應的資源傳回去
基本的比對的速度快、順序不要錯就好了
這邊就選reitit來當我們的router
我們在Branch day8-1 加了滿多東西的
(def app
(ring/ring-handler
(ring/router
[["/api"
["/ping" {:name ::api.ping :get (fn [_] {:status 200, :body "api/pong"})}]
["/user/:id" ::api.user]]
["/users"
{:get (fn [{::r/keys [router]}]
{:status 200
:body (for [i (range 10)]
{:uri (-> router
(r/match-by-name ::user {:id i})
;; with extra query-params
(r/match->path {:iso "möly"}))})})}]
["/users/:id"
{:name ::user
:get (constantly {:status 200, :body "user..."})}]
["/ping" handler]])
(constantly {:status 404, :body ""})))
(comment
(app {:uri "/invalid"})
(app {:request-method :get :uri "/ping"})
(app {:request-method :get :uri "/api/ping"})
(app {:request-method :get, :uri "/users"}) <-- 執行看看結果
)
這邊先提comment,在comment裡面可以放上我們實驗的程式,它都是不會被執行到的
裡面額外放上你的過程對其他要來嘗試的人我覺得幫助很大,實驗、思路等等
可以看到在ring/router需要的是list of list,可以讓我們放入層層資料,子集合以及中間的屬性 <--這很重要,這個結構會出現很多次
list of list就代表有超多個path
來看看最小的 ["/ping" handler]
第一個就是name跟要處理的function
再來是子路徑 ["/api" ["/ping" {:name ... :get ...}]]
這邊每層的路徑外,再加上一些屬性,name 跟 get function
最後稍微複雜一點~
get users
時,它會返回多個user with id的連結,而且在製作這些連結時可以使用route name的名字,最後加上query-parameter
我們中間可以依照情況少寫很多,可以寫的很彈性
然後隨著專案越來越大,router當然不能寫一起,所以在Br day8-2我們將router分開
還記得route結構是list of list,所以每個router回傳list,最後在包成大的list就可以了
(def router
(r/router
[api-router
[...]
["/users/:id"
...]
["/ping" handler]]))
api-router
是在其他地方的程式,回傳list,這樣就能結合在一起了
(打到這裡發現廢話有點多,它功能講超少XDD)
再來先最後一點
Middleware
在判斷完路徑後,就是request in, response out
所以,我們中間可以加工很多事情,也就是Middleware
只要符合這個格式就可以一層一層的做Middleware,包含進來檢查token、出去統一格式等等
礙於篇幅,就先提reitit的1/10功能,其他慢慢介紹